package uniandes.cupi2.tweetSpy.mundo;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Iterator;
import ArbolTrie.Trie;
import ListaSimple.Lista;
import twitter4j.*;
import twitter4j.auth.AccessToken;
import uniandes.cupi2.tweetSpy.twitter.ExceptionTwitter;
import uniandes.cupi2.tweetSpy.twitter.SearchTweets;

public class UsuarioBase extends Usuario
{
	
	// -----------------------------------------------------------------
	// Atributos
	// -----------------------------------------------------------------
	
	private AccessToken accessToken;

	private Trie < Usuario > amigos;

	private Trie < Usuario > followers;

	private Lista < String > palabraIndices;

	private Trie < Tweet > indices;

	private byte[] clave;

	
	// -----------------------------------------------------------------
	// Constructores
	// -----------------------------------------------------------------
	/**
	 * Construye la clase Usuario Base
	 * @param accessToken Access para inicar secion en un futuro,
	 * @param usuario Usuario que se desea agregar.
	 * @param screemName El nombre del usuario.
	 * @param urlFoto La foto del usuario.
	 * @param nClave La clave del usuario.
	 */
	public UsuarioBase ( AccessToken accessToken, User usuario, String screemName, String urlFoto, String nClave ){
		super(usuario, screemName, urlFoto);
		try {
			amigos = new Trie< Usuario >( );
			followers = new Trie< Usuario >( );
			palabraIndices = new Lista< String >( );
			indices = new Trie<Tweet>( );
			clave = MessageDigest.getInstance("MD5").digest( nClave.getBytes( ) );
			this.accessToken = accessToken;	
			obtenerAmigos( );
			obtenerFollowers( );
		} catch (NoSuchAlgorithmException e) {
			// No deberia pasar por aqui.
			e.printStackTrace();
		}
	}

	// -----------------------------------------------------------------
	// Metodos
	// -----------------------------------------------------------------
	
	/**
	 * Inicia secion si el usuario ya existe.
	 * @param nClave Calve del usuario para iniciar secion.
	 * @return Retorna true si lo inica, flase de lo contrario.
	 */
	public boolean iniciarSesion ( String nClave )
	{
		byte[] clvEn = null;
		try {
			clvEn = MessageDigest.getInstance("MD5").digest( nClave.getBytes( ) );
		} catch (NoSuchAlgorithmException e) {
			//No deberia pasar por aqui.
			e.printStackTrace();
		}
		
		if ( clvEn != null )
		{
			for (int i = 0; i < clvEn.length && i < clave.length; i++) {
				if ( clave[i] != clvEn[i] )
				{
					return false;
				}
			}
			Twitter twitter = TwitterFactory.getSingleton( );
			twitter.setOAuthAccessToken( accessToken );
			return true;
		}
		return false;
	}
	
	/**
	 * Extrae la informacion del usuario dado.
	 */
	public void obtenerAmigos ( )
	{
		try {
			Twitter twitter = TwitterFactory.getSingleton( );
			IDs amigosIDs = twitter.getFriendsIDs(-1);
			long[] ids = amigosIDs.getIDs();
			ResponseList<User> amigosActuales = twitter.lookupUsers(ids);
			Iterator<User> iter = amigosActuales.iterator();
			while (iter.hasNext()) {
				User actual = iter.next();
				String screenName = actual.getScreenName();
				Usuario nuevo = new Usuario(actual, screenName,
						actual.getBiggerProfileImageURLHttps());
				amigos.agregar(screenName, nuevo);
			}
		} catch (Exception e) {
			e.printStackTrace( );
			amigos= new Trie< Usuario >( );
		}
	}
	
	/**
	 * Extrae los followers del usuario.
	 */
	public void obtenerFollowers ( )
	{
		try {
			Twitter twitter = TwitterFactory.getSingleton( );
			IDs seguidoresIDs = twitter.getFollowersIDs(-1);
			long[] ids = seguidoresIDs.getIDs();
			ResponseList<User> amigosActuales = twitter.lookupUsers(ids);
			Iterator<User> iter = amigosActuales.iterator();
			while (iter.hasNext()) {
				User actual = iter.next();
				String screenName = actual.getScreenName();
				Usuario nuevo = new Usuario(actual, screenName,
						actual.getBiggerProfileImageURLHttps());
				followers.agregar(screenName, nuevo);
			}
		}
		catch ( Exception e )
		{
			e.printStackTrace( );
			followers = new Trie< Usuario >( );
		}
	}
	
	/**
	 * Devuelve un iterador con los amigos del usuario.
	 * @return Retorna un iterador con los amigos.
	 */
	public Iterator< Usuario > darAmigos ( )
	{
		return amigos.recorridoPreOrden( );
	}
	
	public Iterator < Usuario > darSeguidores ( )
	{
		return followers.recorridoPreOrden( );
	}
	
	/**
	 * Crea un indice con el texto que le entra por parametro. 
	 * @param indice Indice el cual se desa crear.
	 * @return Retorna un iteradoc con el indice creado.
	 * @throws ExceptionTwitter Exception si no se puede buscar el indice.
	 */
	public Iterator<Tweet> crearIndice(String indice) throws ExceptionTwitter {
		try {	
			SearchTweets.buscar( indice, accessToken, indices );
			palabraIndices.agregar( indice );
			return indices.buscar( indice );
		} catch (Exception e) {
			e.printStackTrace( );
			throw new ExceptionTwitter(e.getMessage(), "Creando indice");
		}
	}
	
	public Iterator< String > darIndices ( )
	{
		return palabraIndices.iterator( );
	}
	
	public Iterator< Tweet > darIndice ( String palabra )
	{
		return indices.buscar(palabra);
	}
	
	public Iterator<Usuario>[] buscarAmigos ( String prefijo )
	{
		Iterator<Usuario>[] respuesta = new Iterator[2];
		respuesta[0] = amigos.buscarPorPrefijo(prefijo);
		respuesta[1] = followers.buscarPorPrefijo(prefijo);
		return respuesta;
	}
	
	public Iterator<Tweet> consultarIndicesPorPrefijo(String nPrefijo)
	{
		return indices.buscarPorPrefijo(nPrefijo);
	}
}
